0181. 三斜线指令
- 1. 🎯 本节内容
- 2. 🫧 评价
- 3. 🤔 什么是三斜线指令?
- 4. 🤔 如何使用 reference path 指令?
- 5. 🤔 如何使用 reference types 指令?
- 6. 🤔 如何使用 reference lib 指令?
- 7. 🤔 其他三斜线指令有哪些?
- 8. 🔗 引用
1. 🎯 本节内容
- 三斜线指令的概念和语法
- reference path 指令的使用
- reference types 指令的使用
- reference lib 指令的使用
- 其他三斜线指令
- 使用注意事项
2. 🫧 评价
三斜线指令是 TypeScript 中用于声明文件依赖关系的特殊注释。
- 三斜线指令必须放在文件顶部,之前只能有注释
- 主要用于声明文件之间的依赖关系
- 现代项目中更推荐使用 ES6 import 语句
- 在某些特殊场景下仍然有用,比如引用库类型定义
- 理解三斜线指令有助于维护旧项目和理解类型声明文件
3. 🤔 什么是三斜线指令?
三斜线指令的基本概念。
3.1. 基本语法
ts
/// <reference path="..." />
/// <reference types="..." />
/// <reference lib="..." />
/// <reference no-default-lib="true"/>1
2
3
4
2
3
4
3.2. 使用规则
ts
// ✅ 正确:三斜线指令必须在文件顶部
/// <reference types="node" />
import { readFile } from 'fs'
// ❌ 错误:不能放在代码之后
import { readFile } from 'fs'
/// <reference types="node" /> // ❌ 无效
// ✅ 正确:可以有多个三斜线指令
/// <reference types="node" />
/// <reference types="jest" />
/// <reference lib="es2020" />
import { readFile } from 'fs'
// ✅ 正确:之前可以有注释
/**
* 文件说明
*/
/// <reference types="node" />
import { readFile } from 'fs'1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
3.3. 作用域
ts
// 三斜线指令只影响当前文件
// file1.d.ts
/// <reference types="node" />
// 这里可以使用 Node.js 类型
export function readConfig(): Buffer
// file2.d.ts
// 这里无法使用 Node.js 类型(除非也添加三斜线指令)
export function processData(): void // ❌ Buffer 未定义1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
4. 🤔 如何使用 reference path 指令?
reference path 用于引用其他声明文件。
4.1. 基本用法
ts
// types/models.d.ts
export interface User {
id: string
name: string
}
export interface Post {
id: string
title: string
}
// types/api.d.ts
/// <reference path="./models.d.ts" />
// 现在可以使用 models.d.ts 中的类型
export function getUser(id: string): Promise<User>
export function getPost(id: string): Promise<Post>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
4.2. 引用多个文件
ts
// types/index.d.ts
/// <reference path="./models.d.ts" />
/// <reference path="./api.d.ts" />
/// <reference path="./utils.d.ts" />
// 汇总所有类型定义1
2
3
4
5
6
2
3
4
5
6
4.3. 相对路径
ts
// 项目结构
/**
* types/
* ├── core/
* │ └── base.d.ts
* ├── api/
* │ └── user.d.ts
* └── index.d.ts
*/
// types/api/user.d.ts
/// <reference path="../core/base.d.ts" />
export interface UserAPI extends BaseAPI {
getUser(id: string): Promise<User>
}
// types/index.d.ts
/// <reference path="./core/base.d.ts" />
/// <reference path="./api/user.d.ts" />1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
4.4. 使用场景
ts
// 场景 1:全局声明文件
// types/global.d.ts
/// <reference path="./jquery.d.ts" />
/// <reference path="./lodash.d.ts" />
declare global {
// 扩展全局对象
interface Window {
$: JQueryStatic
_: LoDashStatic
}
}
// 场景 2:出口文件
// index.d.ts
/// <reference path="./types/models.d.ts" />
/// <reference path="./types/api.d.ts" />
export * from './types/models'
export * from './types/api'1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
4.5. 与 import 的对比
ts
// types/api.d.ts
/// <reference path="./models.d.ts" />
// User 类型会被隐式导入到全局作用域
export function getUser(id: string): Promise<User>1
2
3
4
5
2
3
4
5
ts
// types/api.d.ts
import { User } from './models'
// 需要显式导入类型
export function getUser(id: string): Promise<User>1
2
3
4
5
2
3
4
5
5. 🤔 如何使用 reference types 指令?
reference types 用于引用 @types 包。
5.1. 基本用法
ts
// 引用 @types/node 包
/// <reference types="node" />
// 现在可以使用 Node.js 类型
import { readFile } from 'fs'
import { Server } from 'http'
export function createServer(): Server {
// 实现
}1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
5.2. 引用多个类型包
ts
// types/test.d.ts
/// <reference types="node" />
/// <reference types="jest" />
/// <reference types="express" />
// 现在可以使用这些库的类型
import { Server } from 'http'
import { describe, it, expect } from '@jest/globals'
import { Request, Response } from 'express'1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
5.3. 在 tsconfig.json 中配置
ts
// types/global.d.ts
/// <reference types="node" />
/// <reference types="jest" />
// 每个文件都需要添加1
2
3
4
5
2
3
4
5
json
{
"compilerOptions": {
"types": ["node", "jest"]
}
}
// 所有文件自动拥有这些类型1
2
3
4
5
6
7
2
3
4
5
6
7
5.4. 实际应用场景
ts
// 场景 1:测试文件
// test/user.test.ts
/// <reference types="jest" />
describe('User', () => {
it('should create user', () => {
expect(true).toBe(true)
})
})
// 场景 2:Node.js 脚本
// scripts/build.ts
/// <reference types="node" />
import { readFileSync, writeFileSync } from 'fs'
import { resolve } from 'path'
const content = readFileSync(resolve(__dirname, 'template.txt'), 'utf-8')
writeFileSync(resolve(__dirname, 'output.txt'), content)
// 场景 3:库声明文件
// types/my-library.d.ts
/// <reference types="node" />
declare module 'my-library' {
import { EventEmitter } from 'events'
export class MyClass extends EventEmitter {
// ...
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
5.5. 禁用自动引用
json
// tsconfig.json
{
"compilerOptions": {
// 禁用所有 @types 的自动引用
"types": []
}
}1
2
3
4
5
6
7
2
3
4
5
6
7
ts
// 需要显式引用
/// <reference types="node" />
/// <reference types="jest" />1
2
3
2
3
6. 🤔 如何使用 reference lib 指令?
reference lib 用于引用内置库类型定义。
6.1. 基本用法
ts
// 引用 ES2015 库
/// <reference lib="es2015" />
// 现在可以使用 ES2015 特性
const promise = new Promise((resolve) => {
resolve(42)
})
const map = new Map<string, number>()1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
6.2. 引用特定功能库
ts
// 引用 DOM 类型
/// <reference lib="dom" />
// 现在可以使用 DOM API
const element = document.getElementById('app')
element?.addEventListener('click', () => {
console.log('clicked')
})
// 引用 WebWorker 类型
/// <reference lib="webworker" />
// 现在可以使用 Web Worker API
self.addEventListener('message', (event) => {
console.log(event.data)
})1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
6.3. 常用库类型
ts
// ES 标准库
/// <reference lib="es5" />
/// <reference lib="es2015" />
/// <reference lib="es2016" />
/// <reference lib="es2017" />
/// <reference lib="es2018" />
/// <reference lib="es2019" />
/// <reference lib="es2020" />
/// <reference lib="esnext" />
// 分离的 ES 特性库
/// <reference lib="es2015.promise" />
/// <reference lib="es2015.proxy" />
/// <reference lib="es2015.reflect" />
/// <reference lib="es2015.symbol" />
/// <reference lib="es2016.array.include" />
/// <reference lib="es2017.object" />
/// <reference lib="es2017.string" />
// 环境库
/// <reference lib="dom" />
/// <reference lib="dom.iterable" />
/// <reference lib="webworker" />
/// <reference lib="scripthost" />1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
6.4. 实际应用
ts
// 场景 1:Node.js 环境(不需要 DOM)
/// <reference lib="es2020" />
// 不引用 DOM 库,避免误用浏览器 API
export function processData(data: string): string {
// document.getElementById('app'); // ❌ 错误:找不到 document
return data.toUpperCase()
}
// 场景 2:浏览器环境
/// <reference lib="es2020" />
/// <reference lib="dom" />
// 可以使用浏览器 API
export function initApp(): void {
const app = document.getElementById('app')
app?.innerHTML = '<h1>Hello</h1>'
}
// 场景 3:Web Worker
/// <reference lib="webworker" />
// Web Worker 上下文
self.addEventListener('message', (event: MessageEvent) => {
const result = processData(event.data)
self.postMessage(result)
})
function processData(data: any): any {
// 处理逻辑
return data
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
6.5. 与 tsconfig.json 的关系
json
// tsconfig.json
{
"compilerOptions": {
"target": "ES2020",
"lib": ["ES2020", "DOM"] // 全局配置
}
}1
2
3
4
5
6
7
2
3
4
5
6
7
ts
// 文件级别可以覆盖全局配置
/// <reference lib="es2015" />
// 这个文件只使用 ES2015 特性1
2
3
4
2
3
4
7. 🤔 其他三斜线指令有哪些?
其他特殊的三斜线指令。
7.1. reference no-default-lib
ts
// 禁用默认库
/// <reference no-default-lib="true"/>
// 不会自动包含任何库类型定义
// 需要手动引入所需的库
/// <reference lib="es2015.core" />
/// <reference lib="es2015.promise" />
// 只有这些特定的库可用1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
7.2. amd-module
ts
// 为 AMD 模块指定模块名
/// <amd-module name="my-module" />
export function hello() {
return 'Hello'
}
// 编译后的 AMD 模块会使用指定的名称
// define("my-module", ["require", "exports"], ...)1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
7.3. amd-dependency
ts
// 声明 AMD 依赖
/// <amd-dependency path="legacy-lib" />
export function useLib() {
// 使用 legacy-lib
}1
2
3
4
5
6
2
3
4
5
6
7.4. 实际应用示例
ts
// 场景 1:创建轻量级声明文件
/// <reference no-default-lib="true"/>
/// <reference lib="es2015.core" />
/// <reference lib="es2015.promise" />
// 只包含必要的类型定义
export function asyncOperation(): Promise<void>
// 场景 2:AMD 模块命名
/// <amd-module name="app/utils" />
export function format(str: string): string {
return str.trim()
}
// 场景 3:引用外部 AMD 依赖
/// <amd-dependency path="jquery" name="$" />
declare const $: any
export function initUI() {
$('#app').html('Hello')
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
7.5. 使用建议
ts
// ✅ 现代项目推荐:使用 ES6 模块
import { User } from './models'
import type { ApiResponse } from './types'
export function getUser(): Promise<ApiResponse<User>> {
// 实现
}
// ⚠️ 特殊场景可以使用三斜线指令
/// <reference types="node" />
/// <reference lib="dom" />
// 但大多数情况下应该在 tsconfig.json 中配置1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
7.6. 最佳实践
ts
// ❌ 避免:过度使用三斜线指令
/// <reference path="./a.d.ts" />
/// <reference path="./b.d.ts" />
/// <reference path="./c.d.ts" />
/// <reference types="node" />
/// <reference types="jest" />
/// <reference lib="dom" />
// ✅ 推荐:在 tsconfig.json 中统一配置
// tsconfig.json
{
"compilerOptions": {
"types": ["node", "jest"],
"lib": ["ES2020", "DOM"]
}
}
// 使用 ES6 import
import { something } from './a';1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
7.7. 调试技巧
ts
// 查看编译器加载的文件
// tsc --listFiles
// 输出示例:
// node_modules/typescript/lib/lib.es2020.d.ts
// node_modules/@types/node/index.d.ts
// src/index.ts
// src/types.d.ts
// 检查三斜线指令是否生效
/// <reference types="node" />
// 使用 --traceResolution 查看模块解析
// tsc --traceResolution1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14